﻿using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using Comunication;
using TripRemoteObject;

namespace ComunicationServer
{
    class TCPPacketProcessor:ITcpPacketProcessor
    {
        private int _currentClirntId;

        public void ProcessPacket(byte[] buffer, Socket handler)
        {
            UTF8Encoding decoder = new UTF8Encoding();
            string header = decoder.GetString(buffer, 0, 3);
            string cmd = decoder.GetString(buffer, 3, 2);
            int dataLength = int.Parse(decoder.GetString(buffer, 5, 5));
            string data;

            string[] parsedData;
            bool status;
            int clientId;
            decimal distance;
            TripChanges tripObject;

            Commands command = (Commands)int.Parse(cmd);
            try
            {
                switch (command)
                {
                    case Commands.TAKE_VEHICLE:
                        data = decoder.GetString(buffer, 10, dataLength);
                        _currentClirntId = int.Parse(data);
                        
                        ComunicationServerController.Instance.AddClient(int.Parse(data), new Client() { ClientId = _currentClirntId, Handler = handler });
                        ComunicationServerController.Instance.SendMessageQueue(_currentClirntId);
                        
                        Logger.Log(string.Format("Command: {0} client: {1}", command, data));
                        break;
                    case Commands.NOTIFY_VEHICLE_STATUS:
                        data = decoder.GetString(buffer, 10, dataLength);
                        
                        parsedData = data.Split('|');
                        status = bool.Parse(parsedData[0]);
                        clientId = int.Parse(parsedData[1]);
                        distance = decimal.Parse(parsedData[2]);
                        
                        Logger.Log(string.Format("Command: {0} status: {1} client: {2} distance: {3}", command, status, clientId, distance));
                        
                        if (status)
                        {
                            //************************************* TCP *************************************//
                            tripObject = (TripChanges)Activator.GetObject(typeof(TripChanges), Properties.Settings.Default.RemotingURL);
                            //************************************* TCP *************************************//
                            AmountState amountState = tripObject.GetAmountState(clientId, distance, true);
                            ComunicationServerController.Instance.SendClientResponse(clientId, amountState);
                            
                            Logger.Log(string.Format("Message from Payment Server Amount State: {0} status: {1} client: {2} distance: {3}", amountState,
                                                     status, clientId, distance));
                        }

                        break;
                    case Commands.LEAVE_VEHICLE:
                        data = decoder.GetString(buffer, 10, dataLength);
                        parsedData = data.Split('|');
                        clientId = int.Parse(parsedData[0]);
                        distance = decimal.Parse(parsedData[1]);

                        ComunicationServerController.Instance.RemoveClient(clientId);

                        //************************************* TCP *************************************//
                        tripObject = (TripChanges)Activator.GetObject(typeof(TripChanges), Properties.Settings.Default.RemotingURL);
                        //************************************* TCP *************************************//
                        tripObject.GetAmountState(clientId, distance, false);
                        
                        Logger.Log(string.Format("Command: {0} client: {1}", command, data));
                        break;
                    default:
                        break;
                }
            }
            catch (Exception exception)
            {
                Logger.Log(string.Format("Exception on TCP ProcessPacket, command: {0} exception: {1}", command, exception));
            }
        }

        public void EndConnection(Socket handler)
        {
            Logger.Log(string.Format("TCP Connection Ended IP: {0} Port{1}", ((IPEndPoint)handler.RemoteEndPoint).Address, ((IPEndPoint)handler.RemoteEndPoint).Port));
            ComunicationServerController.Instance.RemoveClient(_currentClirntId);
        }
    }
}
